using System;
using System.Collections.Generic;
using System.Linq;

namespace MT5Trade.Models
{
    /// <summary>
    /// 动态止损调整算法类
    /// 基于ATR(平均真实波幅)和历史波动率实现动态止损位调整
    /// 根据市场波动特征自动调整止损位，提高止损的有效性
    /// </summary>
    public class DynamicStopLoss
    {
        #region 常量定义

        // ATR计算参数
        public const int DEFAULT_ATR_PERIOD = 14;        // 默认ATR周期
        public const int MIN_ATR_PERIOD = 5;            // 最小ATR周期
        public const int MAX_ATR_PERIOD = 50;           // 最大ATR周期

        // 动态调整参数
        public const double ATR_MULTIPLIER_LOW_VOL = 1.5;   // 低波动环境ATR倍数
        public const double ATR_MULTIPLIER_MED_VOL = 2.0;   // 中等波动环境ATR倍数
        public const double ATR_MULTIPLIER_HIGH_VOL = 2.5;  // 高波动环境ATR倍数

        // 波动率环境阈值
        public const double LOW_VOLATILITY_THRESHOLD = 0.10;    // 低波动率阈值（年化10%）
        public const double HIGH_VOLATILITY_THRESHOLD = 0.25;   // 高波动率阈值（年化25%）

        // 止损保护参数
        public const double MAX_STOP_DISTANCE_RATIO = 0.08;     // 最大止损距离比例8%
        public const double MIN_STOP_DISTANCE_RATIO = 0.005;    // 最小止损距离比例0.5%

        #endregion

        #region 私有字段

        private readonly RiskMetrics _riskMetrics;
        private readonly List<double> _highPrices;      // 最高价序列
        private readonly List<double> _lowPrices;       // 最低价序列
        private readonly List<double> _closePrices;     // 收盘价序列
        private readonly List<double> _atrValues;       // ATR值序列
        private int _atrPeriod;
        private DateTime _lastUpdateTime;

        #endregion

        #region 构造函数

        /// <summary>
        /// 初始化动态止损算法
        /// </summary>
        /// <param name="riskMetrics">风险度量模块</param>
        /// <param name="atrPeriod">ATR计算周期</param>
        public DynamicStopLoss(RiskMetrics riskMetrics, int atrPeriod = DEFAULT_ATR_PERIOD)
        {
            _riskMetrics = riskMetrics ?? throw new ArgumentNullException(nameof(riskMetrics));
            _atrPeriod = Math.Max(MIN_ATR_PERIOD, Math.Min(MAX_ATR_PERIOD, atrPeriod));
            
            _highPrices = new List<double>();
            _lowPrices = new List<double>();
            _closePrices = new List<double>();
            _atrValues = new List<double>();
            _lastUpdateTime = DateTime.MinValue;
        }

        #endregion

        #region ATR计算方法

        /// <summary>
        /// 更新价格数据并计算ATR
        /// </summary>
        /// <param name="high">最高价</param>
        /// <param name="low">最低价</param>
        /// <param name="close">收盘价</param>
        public void UpdatePriceData(double high, double low, double close)
        {
            if (high < low || close < 0)
            {
                throw new ArgumentException("无效的价格数据");
            }

            _highPrices.Add(high);
            _lowPrices.Add(low);
            _closePrices.Add(close);

            // 计算真实波幅TR
            if (_closePrices.Count >= 2)
            {
                double tr = CalculateTrueRange(_highPrices.Count - 1);
                
                // 计算ATR
                if (_atrValues.Count == 0)
                {
                    // 第一个ATR值使用简单移动平均
                    if (_closePrices.Count >= _atrPeriod)
                    {
                        var recentTR = new List<double>();
                        for (int i = _closePrices.Count - _atrPeriod; i < _closePrices.Count; i++)
                        {
                            recentTR.Add(CalculateTrueRange(i));
                        }
                        _atrValues.Add(recentTR.Average());
                    }
                }
                else
                {
                    // 使用指数移动平均计算ATR
                    double previousATR = _atrValues.Last();
                    double newATR = (previousATR * (_atrPeriod - 1) + tr) / _atrPeriod;
                    _atrValues.Add(newATR);
                }
            }

            // 限制数据长度，保持内存效率
            int maxDataPoints = Math.Max(RiskMetrics.OPTIMAL_DATA_POINTS, _atrPeriod * 3);
            if (_highPrices.Count > maxDataPoints)
            {
                _highPrices.RemoveRange(0, _highPrices.Count - maxDataPoints);
                _lowPrices.RemoveRange(0, _lowPrices.Count - maxDataPoints);
                _closePrices.RemoveRange(0, _closePrices.Count - maxDataPoints);
                _atrValues.RemoveRange(0, _atrValues.Count - maxDataPoints);
            }

            _lastUpdateTime = DateTime.Now;
        }

        /// <summary>
        /// 计算指定位置的真实波幅TR
        /// TR = max(H-L, |H-C_prev|, |L-C_prev|)
        /// </summary>
        /// <param name="index">价格数据索引</param>
        /// <returns>真实波幅值</returns>
        private double CalculateTrueRange(int index)
        {
            if (index <= 0 || index >= _highPrices.Count)
            {
                return _highPrices[index] - _lowPrices[index];
            }

            double hl = _highPrices[index] - _lowPrices[index];
            double hc = Math.Abs(_highPrices[index] - _closePrices[index - 1]);
            double lc = Math.Abs(_lowPrices[index] - _closePrices[index - 1]);

            return Math.Max(hl, Math.Max(hc, lc));
        }

        /// <summary>
        /// 获取当前ATR值
        /// </summary>
        /// <returns>当前ATR值</returns>
        public double GetCurrentATR()
        {
            return _atrValues.Count > 0 ? _atrValues.Last() : 0.0;
        }

        #endregion

        #region 波动率环境分析

        /// <summary>
        /// 分析当前波动率环境
        /// </summary>
        /// <returns>波动率环境类型</returns>
        public VolatilityEnvironment AnalyzeVolatilityEnvironment()
        {
            if (!_riskMetrics.IsDataSufficient())
            {
                return VolatilityEnvironment.Unknown;
            }

            double currentVolatility = _riskMetrics.CalculateVolatility();

            if (currentVolatility <= LOW_VOLATILITY_THRESHOLD)
            {
                return VolatilityEnvironment.Low;
            }
            else if (currentVolatility >= HIGH_VOLATILITY_THRESHOLD)
            {
                return VolatilityEnvironment.High;
            }
            else
            {
                return VolatilityEnvironment.Medium;
            }
        }

        /// <summary>
        /// 根据波动率环境获取ATR倍数
        /// </summary>
        /// <param name="environment">波动率环境</param>
        /// <returns>ATR倍数</returns>
        public double GetATRMultiplier(VolatilityEnvironment environment)
        {
            return environment switch
            {
                VolatilityEnvironment.Low => ATR_MULTIPLIER_LOW_VOL,
                VolatilityEnvironment.Medium => ATR_MULTIPLIER_MED_VOL,
                VolatilityEnvironment.High => ATR_MULTIPLIER_HIGH_VOL,
                _ => ATR_MULTIPLIER_MED_VOL
            };
        }

        #endregion

        #region 动态止损计算

        /// <summary>
        /// 计算基于ATR和波动率的动态止损价格
        /// </summary>
        /// <param name="entryPrice">入场价格</param>
        /// <param name="currentPrice">当前价格</param>
        /// <param name="isLong">是否多头仓位</param>
        /// <param name="customMultiplier">自定义倍数（可选）</param>
        /// <returns>动态止损价格</returns>
        public double CalculateATRBasedStopLoss(double entryPrice, double currentPrice, 
            bool isLong, double? customMultiplier = null)
        {
            if (_atrValues.Count == 0)
            {
                throw new InvalidOperationException("ATR数据不足，无法计算动态止损");
            }

            // 获取当前ATR和波动率环境
            double currentATR = GetCurrentATR();
            var volatilityEnv = AnalyzeVolatilityEnvironment();
            
            // 确定ATR倍数
            double multiplier = customMultiplier ?? GetATRMultiplier(volatilityEnv);
            
            // 计算止损距离
            double stopDistance = currentATR * multiplier;
            
            // 将止损距离转换为比例
            double stopRatio = stopDistance / currentPrice;
            
            // 限制止损比例在合理范围内
            stopRatio = Math.Max(MIN_STOP_DISTANCE_RATIO, 
                          Math.Min(MAX_STOP_DISTANCE_RATIO, stopRatio));
            
            // 计算止损价格
            if (isLong)
            {
                return entryPrice * (1 - stopRatio);
            }
            else
            {
                return entryPrice * (1 + stopRatio);
            }
        }

        /// <summary>
        /// 计算基于波动率的动态跟踪止损
        /// </summary>
        /// <param name="entryPrice">入场价格</param>
        /// <param name="currentPrice">当前价格</param>
        /// <param name="extremePrice">极值价格（多头最高价/空头最低价）</param>
        /// <param name="isLong">是否多头仓位</param>
        /// <param name="holdingTimeHours">持仓时间（小时）</param>
        /// <returns>跟踪止损价格</returns>
        public double CalculateVolatilityBasedTrailingStop(double entryPrice, double currentPrice, 
            double extremePrice, bool isLong, double holdingTimeHours)
        {
            if (!_riskMetrics.IsDataSufficient() || _atrValues.Count == 0)
            {
                // 使用简单的固定比例跟踪止损作为后备方案
                double fallbackRatio = 0.02; // 2%
                return isLong ? extremePrice * (1 - fallbackRatio) : extremePrice * (1 + fallbackRatio);
            }

            // 获取当前ATR和波动率
            double currentATR = GetCurrentATR();
            double currentVolatility = _riskMetrics.CalculateVolatility();
            
            // 使用RiskMetrics的跟踪止损计算方法
            return _riskMetrics.CalculateTrailingStopLoss(
                currentPrice, extremePrice, currentATR, holdingTimeHours, isLong);
        }

        /// <summary>
        /// 计算多层次动态止损
        /// 结合VaR、ATR和时间衰减的综合止损策略
        /// </summary>
        /// <param name="entryPrice">入场价格</param>
        /// <param name="currentPrice">当前价格</param>
        /// <param name="accountEquity">账户净值</param>
        /// <param name="positionValue">仓位价值</param>
        /// <param name="isLong">是否多头仓位</param>
        /// <param name="holdingTimeHours">持仓时间（小时）</param>
        /// <returns>多层次动态止损结果</returns>
        public MultiLevelStopLossResult CalculateMultiLevelStopLoss(double entryPrice, double currentPrice,
            double accountEquity, double positionValue, bool isLong, double holdingTimeHours)
        {
            var result = new MultiLevelStopLossResult();

            try
            {
                // 1. 基于VaR的动态止损
                if (_riskMetrics.IsDataSufficient())
                {
                    result.VaRStopLoss = _riskMetrics.CalculateDynamicStopLoss(
                        entryPrice, accountEquity, positionValue, isLong);
                    
                    result.TimeDecayStopLoss = _riskMetrics.CalculateTimeDecayStopLoss(
                        entryPrice, accountEquity, positionValue, holdingTimeHours, isLong);
                }

                // 2. 基于ATR的动态止损
                if (_atrValues.Count > 0)
                {
                    result.ATRStopLoss = CalculateATRBasedStopLoss(entryPrice, currentPrice, isLong);
                }

                // 3. 选择最优止损价格
                result.RecommendedStopLoss = SelectOptimalStopLoss(
                    entryPrice, currentPrice, isLong, result);

                // 4. 风险等级评估
                result.RiskLevel = EvaluateStopLossRisk(entryPrice, result.RecommendedStopLoss, 
                    accountEquity, positionValue);

                result.IsValid = true;
                result.CalculationTime = DateTime.Now;
            }
            catch (Exception ex)
            {
                result.ErrorMessage = $"计算多层次动态止损时发生异常: {ex.Message}";
                result.IsValid = false;
                
                // 使用保守的后备止损
                double fallbackRatio = 0.02; // 2%
                result.RecommendedStopLoss = isLong ? 
                    entryPrice * (1 - fallbackRatio) : entryPrice * (1 + fallbackRatio);
            }

            return result;
        }

        /// <summary>
        /// 选择最优止损价格
        /// 根据多种止损方法的结果选择最合适的止损位
        /// </summary>
        /// <param name="entryPrice">入场价格</param>
        /// <param name="currentPrice">当前价格</param>
        /// <param name="isLong">是否多头仓位</param>
        /// <param name="stopLossData">多层次止损数据</param>
        /// <returns>最优止损价格</returns>
        private double SelectOptimalStopLoss(double entryPrice, double currentPrice, bool isLong, 
            MultiLevelStopLossResult stopLossData)
        {
            var validStops = new List<double>();

            // 收集所有有效的止损价格
            if (stopLossData.VaRStopLoss > 0) validStops.Add(stopLossData.VaRStopLoss);
            if (stopLossData.ATRStopLoss > 0) validStops.Add(stopLossData.ATRStopLoss);
            if (stopLossData.TimeDecayStopLoss > 0) validStops.Add(stopLossData.TimeDecayStopLoss);

            if (validStops.Count == 0)
            {
                // 使用默认保守止损
                double fallbackRatio = 0.015; // 1.5%
                return isLong ? entryPrice * (1 - fallbackRatio) : entryPrice * (1 + fallbackRatio);
            }

            // 根据持仓方向选择最保守的止损
            if (isLong)
            {
                // 多头选择最高的止损价格（最保守）
                return validStops.Max();
            }
            else
            {
                // 空头选择最低的止损价格（最保守）
                return validStops.Min();
            }
        }

        /// <summary>
        /// 评估止损风险等级
        /// </summary>
        /// <param name="entryPrice">入场价格</param>
        /// <param name="stopLoss">止损价格</param>
        /// <param name="accountEquity">账户净值</param>
        /// <param name="positionValue">仓位价值</param>
        /// <returns>风险等级</returns>
        private string EvaluateStopLossRisk(double entryPrice, double stopLoss, 
            double accountEquity, double positionValue)
        {
            double stopLossRatio = Math.Abs(stopLoss - entryPrice) / entryPrice;
            double accountRisk = (stopLossRatio * positionValue) / accountEquity;

            if (accountRisk <= 0.01)
                return "低风险";
            else if (accountRisk <= 0.03)
                return "中等风险";
            else if (accountRisk <= 0.05)
                return "较高风险";
            else
                return "高风险";
        }

        #endregion

        #region 状态和诊断方法

        /// <summary>
        /// 获取当前状态信息
        /// </summary>
        /// <returns>状态信息</returns>
        public (int DataCount, double CurrentATR, VolatilityEnvironment Environment, DateTime LastUpdate) GetStatus()
        {
            var environment = AnalyzeVolatilityEnvironment();
            double currentATR = GetCurrentATR();
            
            return (_closePrices.Count, currentATR, environment, _lastUpdateTime);
        }

        /// <summary>
        /// 设置ATR计算周期
        /// </summary>
        /// <param name="period">新的ATR周期</param>
        public void SetATRPeriod(int period)
        {
            int newPeriod = Math.Max(MIN_ATR_PERIOD, Math.Min(MAX_ATR_PERIOD, period));
            if (newPeriod != _atrPeriod)
            {
                _atrPeriod = newPeriod;
                // 清除现有ATR值，强制重新计算
                _atrValues.Clear();
            }
        }

        /// <summary>
        /// 检查数据充分性
        /// </summary>
        /// <returns>数据是否充分</returns>
        public bool IsDataSufficient()
        {
            return _closePrices.Count >= _atrPeriod && _riskMetrics.IsDataSufficient();
        }

        #endregion
    }

    #region 相关数据类型定义

    /// <summary>
    /// 波动率环境枚举
    /// </summary>
    public enum VolatilityEnvironment
    {
        Unknown,    // 未知
        Low,        // 低波动
        Medium,     // 中等波动
        High        // 高波动
    }

    /// <summary>
    /// 多层次止损结果类
    /// </summary>
    public class MultiLevelStopLossResult
    {
        public double VaRStopLoss { get; set; }          // VaR止损价格
        public double ATRStopLoss { get; set; }          // ATR止损价格
        public double TimeDecayStopLoss { get; set; }    // 时间衰减止损价格
        public double RecommendedStopLoss { get; set; }  // 推荐止损价格
        public string RiskLevel { get; set; } = string.Empty;  // 风险等级
        public bool IsValid { get; set; }                // 结果是否有效
        public string ErrorMessage { get; set; } = string.Empty; // 错误信息
        public DateTime CalculationTime { get; set; }    // 计算时间
    }

    #endregion
}


